/**
 * mapbox地图方法
 */
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
// import MapboxLanguage from '@mapbox/mapbox-gl-language';
import axios from 'axios';
import _ from 'lodash-es';
import MapboxGL from 'mapbox-gl';
import 'mapbox-gl-plugin-layer-group';
// 绘图用的插件
import 'mapbox-gl/dist/mapbox-gl.css';
import proj4 from 'proj4';
import { useMapStore } from '@/stores';
import { DEFAULT_MAP_STATE, LAYERS_GROUP_ID, TD_CIA_URL, TD_IMG_URL } from './map-helper';
import { measureArea, closeMeasureArea } from './map-measure-area';
import { measureLineLength, closeMeasureLine } from './map-measure-distance';

let draw = null;
let popup = null;
let updatePoint = null;

const mapStore = useMapStore();

// * 保存地图实例
export let map = null;

/**
 *  初始化地图
 * @param {string} ID 容器id
 */

export function MAP_2D_INIT(ID) {
  map = new MapboxGL.Map({
    container: ID,
    style: {
      version: 8,
      glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
      sources: {},
      layers: [],
    },
    center: [DEFAULT_MAP_STATE.longitude, DEFAULT_MAP_STATE.latitude],
    zoom: DEFAULT_MAP_STATE.zoom,
    bearing: DEFAULT_MAP_STATE.bearing,
    pitch: DEFAULT_MAP_STATE.pitch,

    minZoom: 4,
    maxZoom: 16,
  });

  //解决canvas渲染不正确
  map.on('styledata', function () {
    map.resize();
  });

  let controls = map._controls;

  controls.forEach((control) => {
    if ('_updateLogo' in control) {
      map.removeControl(control);
    }

    // 去除attribute控件
    if ('_attribHTML' in control) {
      map.removeControl(control);
    }
  });

  map.touchZoomRotate.disableRotation();

  // 如果还需要禁用通过按键（如Shift + 拖动）来旋转地图，也可以添加以下代码
  map.keyboard.disable();

  draw = new MapboxDraw({
    displayControlsDefault: false,
  });

  map.addControl(draw);

  //去除mapbox的logo
  map._logoControl && map.removeControl(map._logoControl);

  // map.addControl(
  //   new MapboxLanguage({
  //     defaultLanguage: 'zh-Hans',
  //   }),
  // );

  // * 添加图层组
  map.once('load', () => {
    // 添加所有的图层组（占位图层）
    _.map(LAYERS_GROUP_ID, (id) => {
      map.addLayerGroup(id);
    });
    // 添加底图

    CHANGE_MAPBOX_BASE_LAYER(map);
    CHANGE_MAPBOX_BASE_LABEL_LAYER(map);
    // * 地图初始化成功
    mapStore.INITIALIZE('2d');
  });

  window.map2d = map;

  return map;
}

/**
 * 获取map
 */
export const GET_MAPBOX_MAP = () => {
  return map;
};

/**
 * mapbox切换底图
 * @param { String } id 要切换的底图类型
 */
export const CHANGE_MAPBOX_BASE_LAYER = (MAP) => {
  const layerId = LAYERS_GROUP_ID.TD_BASE_MAP;
  let sources;

  // 移除原来图层
  REMOVE_MAPBOX_LAYER(layerId, MAP);

  sources = {
    TD_IMG: {
      id: layerId,
      type: 'raster',
      tiles: TD_IMG_URL,
      tileSize: 256,
    },
  };

  let layers = {
    id: layerId,
    type: 'raster',
    source: sources.TD_IMG,
  };

  MAP.addLayerToGroup(layerId, layers);
};

/**
 * mapbox切换标注
 * @param { String } id 要切换的底图类型
 */
export const CHANGE_MAPBOX_BASE_LABEL_LAYER = (MAP) => {
  const layerId = LAYERS_GROUP_ID.TD_BASE_LABEL_MAP;
  let sources;

  // 移除原来图层
  REMOVE_MAPBOX_LAYER(layerId, MAP);

  sources = {
    TD_IMG: {
      id: layerId,
      type: 'raster',
      tiles: TD_CIA_URL,
      tileSize: 256,
    },
  };

  let layers = {
    id: layerId,
    type: 'raster',
    source: sources.TD_IMG,
  };

  MAP.addLayerToGroup(layerId, layers);
};

/**
 * 切换地图样式(mapbox底图)
 * @param {*} data Mapbox地图样式
 * @param {*} MAP 地图实例
 */
export const MAP_STYLE_SWITCHER = (data, MAP) => {
  let token = 'pk.eyJ1IjoibXJ3YW5nMTIxMiIsImEiOiJjanQ1ZnF2M3QwNXliNDNvN3htMWYyODljIn0.eBdPKjo6n3odkn4thCjCxg';

  axios
    .get(`https://api.mapbox.com/styles/v1/${data}?access_token=${token}`)
    .then((result) => {
      const { data: newStyle } = result;
      const currentStyle = MAP.getStyle();

      newStyle.sources = Object.assign({}, currentStyle.sources, newStyle.sources);

      let Layers = newStyle.layers.filter((el) => {
        //去掉mapbox底图地名标注
        return !el.id.includes('-label');
      });

      const appLayers = currentStyle.layers.filter((el) => {
        return (
          (el.source &&
            el.source != 'mapbox://mapbox.satellite' &&
            el.source != 'mapbox' &&
            el.source != 'composite') ||
          el.id.includes('TD_BASE') ||
          el.id.includes('MAP_LAYER') ||
          el.id.includes('MEASURE_POINT')
        );
      });

      Layers = [...Layers, ...appLayers];
      newStyle.layers = Layers;
      MAP.setStyle(newStyle);
    })
    .catch((error) => {
      console.error(error);
    });
};

/**
 * 重置地图样式(切换为天地图底图时使用)
 * @param {*} MAP 地图实例
 */
export const MAP_STYLE_RESET = (MAP = map) => {
  const currentStyle = MAP.getStyle();

  const appLayers = currentStyle.layers.filter((el) => {
    return el.id.includes('TD_BASE') || el.id.includes('MAP_LAYER') || el.id.includes('MEASURE_POINT');
  });

  let newStyle = {};

  newStyle.layers = [...appLayers];
  newStyle.glyphs = 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf';
  newStyle.version = 8;
  newStyle.sources = currentStyle.sources;

  delete newStyle.sprite;

  MAP.setStyle(newStyle);
};

/**
 * mapbox移除指定图层
 * @param {string} layerId 图层id
 */
export function REMOVE_MAPBOX_LAYER(layerId, MAP = map) {
  if (MAP.getLayer(layerId)) {
    MAP.removeLayer(layerId);
    MAP.removeSource(layerId);
  }
}

/**
 * 移除map_img
 */
export const REMOVE_MAP_IMG = (ID) => {
  if (map?.hasImage(ID)) {
    map?.removeImage(ID);
  }
};

/**
 * mapbox移除地图
 * @export
 */
export function REMOVE_2D_MAP() {
  window.map2d = null;

  map && map.remove();
  map = null;
}

/**
 * mapbox 跳转地图到指定位置和指定级别
 * @param {Object} latLang 经纬度数组
 * @param {Number} zoom 地图缩放级别
 */
export function MapBoxFlyTo(latLang, zoom) {
  map.flyTo({
    center: latLang, // 中心点坐标
    zoom: zoom,
  });
}

/**
 * mapbox 放大地图缩放级别
 */
export function MapBoxMagnifyZoom() {
  map.zoomIn();
}

/**
 * mapbox 缩小地图缩放级别
 */
export function MapBoxReduceZoom() {
  map.zoomOut();
}

/**
 * 切换3D
 */
export function mapTo3d(type) {
  if (type == '2d') {
    map.setProjection('globe');
    map.flyTo({
      pitch: 60,
      zoom: 12,
      bearing: 45,
      speed: 0.5,
    });
    map.setFog({
      color: 'rgba(66, 88, 106, 1.0)',
    });

    // Add some 3D terrain
    map.addSource('mapbox-dem', {
      type: 'raster-dem',
      url: 'mapbox://mapbox.terrain-rgb',
      tileSize: 512,
      maxzoom: 14,
    });
    map.setTerrain({
      source: 'mapbox-dem',
      exaggeration: 5,
    });
    window.requestAnimationFrame(frame);

    mapStore.CHANGE_MODE('3d');
  } else {
    if (map.getSource('mapbox-dem')) {
      map.setTerrain();
      map.removeSource('mapbox-dem');
    }

    map.setProjection('mercator');
    map.flyTo({
      pitch: 0,
      zoom: 9,
      bearing: 0,
      speed: 0.5,
    });

    mapStore.CHANGE_MODE('2d');
  }
}

let lastTime = 0.0;
let cycleTime = 0.0;
let night = true;

function frame(time) {
  const elapsedTime = (time - lastTime) / 1000.0;

  cycleTime += elapsedTime;

  if (cycleTime >= 50.0) {
    if (night) {
      map.setFog({
        color: 'rgba(216, 242 ,255, 1.0)',
      });
    } else {
      map.setFog({
        color: 'rgba(66, 88, 106, 1.0)',
      });
    }

    night = !night;
    cycleTime = 0.0;
  }

  lastTime = time;

  window.requestAnimationFrame(frame);
}

/**
 * 重置地图位置
 */
export const REST_MAP_FIT_BOUNDS = () => {
  const bbox = [90.52643750000135, 46.08512949598068, 79.97956250000101, 42.73136948754305];

  // 界线
  map.fitBounds(
    [
      [bbox[0], bbox[1]],
      [bbox[2], bbox[3]],
    ],
    {
      padding: { top: 100, bottom: 100, left: 100, right: 100 },
      maxZoom: 7,
    },
  );
};

/**
 * =========测量功能=========
 */
/**
 * 添加绘图工具
 */

export const ADD_DRAW = (option = {}) => {
  if (draw) {
    REMOVE_DRAW();
  }

  draw = new MapboxDraw({
    displayControlsDefault: false,

    ...option,
  });
  map.addControl(draw);
};

/**
 * 移除绘图工具
 */
export const REMOVE_DRAW = () => {
  if (!draw) return;

  draw.deleteAll();

  map.removeControl(draw);
  draw = null;
};

/**
 * 地图测量功能-清除
 */
export const MEASURE_CLEAR = () => {
  ADD_DRAW();

  if (popup) {
    popup.remove();
  }

  map.off('click', updatePoint);

  draw.deleteAll();
  REMOVE_MAPBOX_LAYER(LAYERS_GROUP_ID.MEASURE_POINT);
  REMOVE_MAP_IMG('pulsing-dot');
};

/**
 * 地图测量功能-测面
 */
export const MEASURE_AREA_V = () => {
  MEASURE_CLEAR();
  measureArea(map);
};

/**
 * 地图测量功能-测距
 */
export const MEASURE_LINE_V = () => {
  MEASURE_CLEAR();
  measureLineLength(map);
};

/**
 * 地图测量功能-清除
 */
export const MEASURE_CLEAR_V = () => {
  closeMeasureLine(map);
  closeMeasureArea(map);
  map.getCanvas().style.cursor = 'pointer';
};

/**
 * 地图测量功能-坐标测量
 */

export const MEASURE_POINT = () => {
  proj4.defs('EPSG:4546', '+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs');

  updatePoint = (e) => {
    REMOVE_MAPBOX_LAYER(LAYERS_GROUP_ID.MEASURE_POINT);
    REMOVE_MAP_IMG('pulsing-dot');

    POINT_MARKER(e.lngLat);

    const xy = proj4('EPSG:4546', [e.lngLat.lng, e.lngLat.lat]);

    popup = new MapboxGL.Popup({ anchor: 'bottom', offset: 15 })
      .setLngLat(e.lngLat)
      .setHTML(
        `<div style="width:172px;border-radius: 13px;text-align:left;font-size:14px">
        <div style="margin-bottom:8px">X坐标: ${xy[0].toFixed(5)}</div>
        <div >Y坐标: ${xy[1].toFixed(5)}</div>
        </div>`,
      )
      .addTo(map);

    if (popup) {
      popup.on('close', () => {
        REMOVE_MAPBOX_LAYER(LAYERS_GROUP_ID.MEASURE_POINT);
      });
    }
  };

  map.off('click', updatePoint);
  map.on('click', updatePoint);
};

export const POINT_MARKER = (values) => {
  const size = 100;

  const pulsingDot = {
    width: size,
    height: size,
    data: new Uint8Array(size * size * 4),

    onAdd: function () {
      const canvas = document.createElement('canvas');

      canvas.width = this.width;
      canvas.height = this.height;
      this.context = canvas.getContext('2d');
    },

    render: function () {
      const radius = (size / 2) * 0.3;
      const context = this.context;

      context.beginPath();
      context.arc(this.width / 2, this.height / 2, radius, 0, Math.PI * 2);
      context.fillStyle = '#ffffff';
      context.strokeStyle = 'rgba(255, 100, 100, 1)';
      context.lineWidth = 10;
      context.fill();
      context.stroke();

      this.data = context.getImageData(0, 0, this.width, this.height).data;

      map.triggerRepaint();

      return true;
    },
  };

  map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });

  const layer = {
    id: LAYERS_GROUP_ID.MEASURE_POINT,
    type: 'symbol',
    source: {
      type: 'geojson',
      data: {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: [values.lng, values.lat],
            },
          },
        ],
      },
    },
    layout: {
      'icon-image': 'pulsing-dot',
    },
  };

  map.addLayerToGroup(LAYERS_GROUP_ID.MEASURE_POINT, layer);
};
